<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <!-- import CSS -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <link rel="stylesheet" href="/icon/iconfont.css">
    <!-- import Vue before Element -->
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <!-- import JavaScript -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js" charset="UTF-8"></script>
    <script type="text/javascript" src="/js/jquery.ZResize.js" charset="UTF-8"></script>
    <script type="text/javascript" src="/js/sockjs.min.js" charset="UTF-8"></script>
    <script type="text/javascript" src="/js/stomp.min.js" charset="UTF-8"></script>
    <script src="/js/util.js"></script>
    <script src="/js/constant.js"></script>
    <title>拍照功能</title>
</head>
<body>
<div id="app">
    <div class="container">
        <el-col :span="10.5">
            <el-card shadow="always">
                <div style="width: 804px;height: 593px;border: 1px solid #CCCCCC; overflow:hidden;position: relative;">
                    <div class="video_parent_div">
                        <video id="video"
                               style="position: absolute;left: 0;top: 0;width: 100%;height: 100%;object-fit: cover"
                               @dblclick="fullScreen">
                            您的浏览器不支持 video 标签。
                        </video>
                        <!-- 承载手动框选操作 -->
                        <div id="screenshot_full_div"></div>
                        <div class="screenshot_div" id="id_pic_shotscreen"></div>
                        <!-- 配置选择 -->
                        <div class="div_handle_select">
                            <div class="div_handle_select-title" id="drag_handle_select">
                                <span id="title_font">配置选择</span>
                                <span id="title_xx" @click="closeHandleConfig">✕</span>
                            </div>
                            <div class="div_handle_select-content">
                                <el-form ref="form" :model="form" label-width="100px">
                                    <el-form-item label="保存路径：" :inline="true">
                                        <el-input v-model="form.savePath" placeholder="请输入保存路径"
                                                  style="width: 234px"></el-input>
                                    </el-form-item>
                                    <el-form-item label="设备列表：">
                                        <el-select v-model="form.deviceList" placeholder="请选择媒体设备" style="width: 234px"
                                                   @change="changeDevice">
                                            <el-option v-for="item in devOptions"
                                                       :key="item.value"
                                                       :label="item.label"
                                                       :value="item.value"></el-option>
                                        </el-select>
                                    </el-form-item>
                                    <el-form-item label="视频模式：">
                                        <el-select v-model="form.videoType" placeholder="请选择视频模式" style="width: 234px">
                                            <el-option v-for="item in videoOptions"
                                                       :key="item.value"
                                                       :label="item.label"
                                                       :value="item.value"></el-option>
                                        </el-select>
                                    </el-form-item>
                                    <el-form-item label="分辨率：">
                                        <el-select v-model="form.resolution" placeholder="请选择分辨率" style="width: 234px"
                                                   @change="changeResolution">
                                            <el-option v-for="item in resOptions"
                                                       :key="item.value"
                                                       :label="item.label"
                                                       :value="item.value"></el-option>
                                        </el-select>
                                    </el-form-item>
                                    <el-form-item>
                                        <el-button type="primary" @click="onSubmit">确定</el-button>
                                        <el-button @click="resetForm('form')">重置</el-button>
                                    </el-form-item>
                                </el-form>
                            </div>
                        </div>
                        <div class="aron_div_cas">
                            <ul>
                                <li><span id="left_aron" @click="turnLeft" title="左转"><i
                                        class="iconfont icon-zuoxuanzhuan"></i></span>
                                </li>
                                <li><span id="right_aron" @click="turnRight" title="右旋"><i
                                        class="iconfont icon-youxuanzhuan"></i></span>
                                </li>
                            </ul>
                        </div>
                    </div>
                    <div class="pick_canvas">
                        <canvas id="canvas" width="100%" height="100%" style="display: none;"></canvas>
                        <img src="" alt="图片显示不正确" id="pick_img"/>
                    </div>
                </div>
                <div class="pop_div_cas">
                    <el-popover
                            placement="top"
                            width="774"
                            trigger="manual" v-model="visible">
                        <div class="pop_div_cas_inner">
                            <ul>
                                <li @click="openVideo">
                                    <i class="iconfont icon-shipin"></i>
                                    <span>打开视频</span>
                                </li>
                                <li @click="closeVideo">
                                    <i class="iconfont icon-guanbishipin"></i>
                                    <span>关闭视频</span>
                                </li>
                                <li @click="testScan">
                                    <i class="iconfont icon-paizhao"></i>
                                    <span>拍照</span>
                                </li>
                                <li @click="handleSelect" id="handle_select_li">
                                    <i class="iconfont icon-jieping"></i>
                                    <span>手动框选</span>
                                </li>
                                <li @click="configSelect">
                                    <i class="iconfont icon-shezhi"></i>
                                    <span>配置选择</span>
                                </li>
                            </ul>
                        </div>
                        <el-button slot="reference" id="handle_pic_btn" @click="visible = !visible">手动拍照</el-button>
                    </el-popover>
                </div>
            </el-card>
        </el-col>
    </div>
</div>
</body>
<script>

    let video;

    let canvas;

    let context;

    let mediaStreamTrack;

    // 设备列表map，key为deviceId,value为设备对象
    let videoMap = {};

    let currentDeviceID;  // 当前设备

    let deviceTimer;  // 定时器

    let svWidth = 100;  // 原始尺寸宽

    let svHeight = 100;  // 原始尺寸高

    let transeg = 0; // 初始旋转角度，每次点击增加90

    let isDownRect = false; // 是否按下

    let isDownLive = false; // 直播窗口拖动按下

    let isDownPic = false; // 高拍仪拖动按下

    let isHandleSelect = false; // 是否手动框选操作

    let picWidth = 4416; // 需要拍照的图片宽，默认640

    let picHeight = 3312; // 需要拍照的图片高，默认480

    let picY = 0; // 需要拍照的图片x坐标

    let picX = 0; // 需要拍照的图片y坐标

    let doHandArea = false; // 默认没有手动框选

    let sampUtil = new SampUtil();

    new Vue({
        el: '#app',
        data()
        {
            return {
                stream_url: '',
                validate_time: '',
                form: {
                    videoType: 0,
                    resolution: '4416*3312',
                    deviceList: '',
                    savePath: "D:\\eloadFiles\\videos"
                },
                videoOptions: [{
                    value: 0,
                    label: "YUY2"
                }],
                devOptions: [],
                resOptions: [{
                    value: '4416*3312',
                    label: '4416 * 3312'
                }, {
                    value: '4160*3120',
                    label: '4160 * 3120'
                }, {
                    value: '3840*2160',
                    label: '3840 * 2160'
                }, {
                    value: '3264*2448',
                    label: '3264 * 2448'
                }, {
                    value: '2592*1944',
                    label: '2592 * 1944'
                }, {
                    value: '2048*1536',
                    label: '2048 * 1536'
                }, {
                    value: '1920*1080',
                    label: '1920 * 1080'
                }, {
                    value: '1600*1200',
                    label: '1600 * 1200'
                }, {
                    value: '1280*1024',
                    label: '1280 * 1024'
                }, {
                    value: '1280*960',
                    label: '1280 * 960'
                }, {
                    value: '1280*720',
                    label: '1280 * 720'
                }, {
                    value: '960*800',
                    label: '960 * 800'
                }, {
                    value: '800*600',
                    label: '800 * 600'
                }, {
                    value: '640*480',
                    label: '640 * 480'
                }],
                visible: false
            };
        },
        methods: {
            testScan()
            {
                // 手动拍照使用时间缀做为文件名
                let curTime = sampUtil.getCurrentTime();
                let nameTime = curTime.replaceAll("-", "").replaceAll(":", "").replaceAll(" ", "");
                this.scanAndSave(this.form.savePath, nameTime);
            },
            // 左转
            turnLeft()
            {
                transeg -= 90
                $("#video").css({
                    "transform": "rotate(" + transeg + "deg)",
                    "-ms-transform": "rotate(" + transeg + "deg)", /* Internet Explorer */
                    "-moz-transform": "rotate(" + transeg + "deg)", /* Firefox */
                    "-webkit-transform": "rotate(" + transeg + "deg)", /* Safari 和 Chrome */
                    "-o-transform": "rotate(" + transeg + "deg)", /* Opera */
                });
                if (transeg == -360)
                {
                    transeg = 0;
                }
            },
            // 右转
            turnRight()
            {
                transeg += 90;
                $("#video").css({
                    "transform": "rotate(" + transeg + "deg)",
                    "-ms-transform": "rotate(" + transeg + "deg)", /* Internet Explorer */
                    "-moz-transform": "rotate(" + transeg + "deg)", /* Firefox */
                    "-webkit-transform": "rotate(" + transeg + "deg)", /* Safari 和 Chrome */
                    "-o-transform": "rotate(" + transeg + "deg)", /* Opera */
                });
                if (transeg == 360)
                {
                    transeg = 0;
                }
            },
            // 配置选择确定
            onSubmit()
            {
                if (this.form.savePath == '' || this.form.savePath == undefined)
                {
                    this.$message.error('请输入保存路径');
                }
                else
                {
                    this.$message({
                        message: '配置完成',
                        type: 'success'
                    });
                    $(".div_handle_select").css("display", "none");
                }
            },
            // 重置
            resetForm(formName)
            {
                this.$refs[formName].resetFields();
            },
            /**
             * MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可，媒体输入会产生一个MediaStream，
             * 里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道（来自硬件或者虚拟视频源，比如相机、
             * 视频采集设备和屏幕共享服务等等）、一个音频轨道（同样来自硬件或虚拟音频源，比如麦克风、A/D转换器等等），
             * 也可能是其它轨道类型。
             * @param constraints constraints 参数是一个包含了video 和 audio两个成员的MediaStreamConstraints 对象，
             *                      用于说明请求的媒体类型。必须至少一个类型或者两个同时可以被指定。如果浏览器无法找到
             *                      指定的媒体类型或者无法满足相对应的参数要求，那么返回的Promise对象就会处于rejected［失败］状态，
             *                      NotFoundError作为rejected［失败］回调的参数。
             * @param success 加载成功回调函数
             * @param error 加载失败回调函数
             */
            getUserMedia(constraints, success, error)
            {
                if (navigator.mediaDevices.getUserMedia)
                {
                    //最新的标准
                    navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
                } else if (navigator.webkitGetUserMedia)
                {
                    //webkit核心浏览器
                    navigator.webkitGetUserMedia(constraints, success, error)
                } else if (navigator.mozGetUserMedia)
                {
                    //firfox浏览器
                    navigator.mozGetUserMedia(constraints, success, error);
                } else if (navigator.getUserMedia)
                {
                    //旧版
                    navigator.getUserMedia(constraints, success, error);
                }
            },
            success(stream)
            {
                mediaStreamTrack = stream.getTracks()[0];
                this.form.deviceList = mediaStreamTrack.label.split("(")[0]
                if (!video)
                {
                    return false;
                }
                // 旧的浏览器可能没有srcObject
                if ("srcObject" in video)
                {
                    video.srcObject = stream;
                } else
                {
                    // 防止再新的浏览器里使用它，应为它已经不再支持了
                    video.src = window.URL.createObjectURL(stream);
                }
                video.play();
            },
            error(error)
            {
                console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
            },

            /**
             * 初始化对象操作
             */
            initVideoObj()
            {
                video = document.getElementById('video');
                canvas = document.getElementById('canvas');
                context = canvas.getContext('2d');
            },
            createVideoScan(resWidth, resHeight, curDevId)
            {
                if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia)
                {
                    //调用用户媒体设备, 访问摄像头
                    this.getUserMedia({
                            video: {
                                deviceId: curDevId,
                                width: resWidth,
                                height: resHeight,
                            },
                        },
                        this.success,
                        this.error);
                } else
                {
                    alert('不支持访问用户媒体');
                }
            },
            /**
             * 拍照，并返回最终的图片数据，压缩比例默认为0.7
             */
            scan()
            {
                if (mediaStreamTrack == undefined)
                {
                    this.$message.error('视频未打开');
                    return false;
                }
                // 转化角度为正值
                let trueEg = this.transegByAction(transeg);
                let trueScale = trueEg / 90;  // 计算最终的倍数
                // 获取框选区域大小和位置
                this.calcPicPosition();
                // 根据因子拍照
                this.scanByScale(trueScale, context);
                // 保存数据到预览图片中
                let imgData = canvas.toDataURL("image/jpeg", SCAN_PIC_QUALITY);
                $(".pick_canvas").css("display", "block");
                $("#pick_img").attr("src", imgData).css({
                    "width": "100%",
                    "height": "100%"
                });
                // 3秒之后消失
                setTimeout(function ()
                {
                    $(".pick_canvas").css("display", "none");
                }, 3000);
                return imgData;
            },
            /**
             * 自动框选
             * @param width 选框宽
             * @param height 选框高
             * @param resizeX 坐标x，默认为0
             * @param resizeY 坐标y，默认为0
             */
            autoSelect(width, height, resizeX, resizeY)
            {
                $("#handle_select_li").css({
                    "font-weight": "bolder",
                    "border": "1px solid #0896ba"
                });
                $(".screenshot_div, .resize-panel").css({
                    "width": width + "px",
                    "height": height + "px",
                });
                if (resizeX == undefined)
                {
                    resizeX = 0;
                }
                if (resizeY == undefined)
                {
                    resizeY = 0;
                }
                $(".screenshot_div").css({
                    "top": resizeX + "px",
                    "left": resizeY + "px"
                });
                $(".screenshot_div").css("display", "block");
            },
            /**
             * 拍照并保存图片到服务上
             * @param savePath 保存的路径
             * @param orderNum 当前订单号
             */
            scanAndSave(savePath, orderNum)
            {
                let imgData = this.scan();
                $.ajax({
                    url: "/savePicture",
                    data: {
                        imgData: imgData,
                        savePath: savePath,
                        imgName: orderNum, // 使用订单作为图片名称
                    },
                    type: "POST",
                    dataType: "JSON",
                    success: (res) =>
                    {
                        if (res.code == 200)
                        {
                            this.$message({
                                type: "success",
                                message: "图片保存到服务器成功，订单号为：" + orderNum
                            });
                        } else if (res.code == 8007)
                        {
                            this.$message({
                                type: "warn",
                                message: "图片保存成功，但未查到任何订单信息，图片信息入库失败，订单号为：" + orderNum
                            });
                        }
                        else
                        {
                            this.$message({
                                type: "success",
                                message: "后台系统服务器异常，图片入库失败，订单号为：" + orderNum
                            });
                        }
                    },
                    error: (err) =>
                    {
                    }
                })
            },
            /**
             * 计算框选区域位置和大小
             */
            calcPicPosition()
            {
                // 根据当前框选区域最小宽高和父级窗体最小宽高计算比例
                let fullShotWidth = parseFloat($("#screenshot_full_div").css("width").replace("px", ""));
                let fullShotHeight = parseFloat($("#screenshot_full_div").css("height").replace("px", ""));
                let shotMinWidth = parseFloat($("#id_pic_shotscreen").css("width").replace("px", ""));
                let shotMinHeight = parseFloat($("#id_pic_shotscreen").css("height").replace("px", ""));

                // 根据当前分辨率计算x和y实例值
                let width = this.form.resolution.split("\*")[0];
                let height = this.form.resolution.split("\*")[1];

                let shotWidth = parseFloat($("#id_pic_shotscreen").css("width").replace("px", ""));
                let shotHeight = parseFloat($("#id_pic_shotscreen").css("height").replace("px", ""));
                let shotTop = parseFloat($("#id_pic_shotscreen").css("top").replace("px", ""));
                let shotLeft = parseFloat($("#id_pic_shotscreen").css("left").replace("px", ""));
                if (shotWidth > 5)
                {
                    picWidth = shotWidth;
                    picWidth = width / fullShotWidth * shotMinWidth;
                }
                if (shotHeight > 5)
                {
                    picHeight = shotHeight
                    picHeight = height / fullShotHeight * shotMinHeight;
                }
                if (shotTop > 0)
                {
                    picY = shotTop;
                    picY = height / fullShotHeight * picY;
                }
                if (shotLeft > 0)
                {
                    picX = shotLeft;
                    picX = width / fullShotWidth * picX;
                }
                if (shotWidth > 5 || shotHeight > 5)
                {
                    doHandArea = true;
                }
                else
                {
                    doHandArea = false;
                }
            },
            /**
             * @param trueScale 实例的角度倍数
             * @param context canvas.context实例
             */
            scanByScale(trueScale, context)
            {
                canvas.width = picWidth;
                canvas.height = picHeight;
                context.save();
                console.log(doHandArea)
                // 判断是否有做框选，若没有框选，则拍全屏图
                if (!doHandArea)
                {
                    context.drawImage(video, picX, picY, picWidth, picHeight);
                    context.restore();
                    return false;
                }
                switch (trueScale)
                {
                    case 0:
                        context.drawImage(video, picX, picY, picWidth, picHeight, 0, 0, picWidth, picHeight);
                        break;
                    case 1:
                        context.rotate(90 * Math.PI / 180);
                        context.drawImage(video, picX, picY, picWidth, picHeight, 0, -picHeight, picWidth, picHeight);
                        break;
                    case 2:
                        context.rotate(180 * Math.PI / 180);
                        context.drawImage(video, picX, picY, picWidth, picHeight, -picWidth, -picHeight, picWidth,
                            picHeight);
                        break;
                    case 3:
                        context.rotate(270 * Math.PI / 180);
                        context.drawImage(video, picX, picY, picWidth, picHeight, -picWidth, 0, picWidth, picHeight);
                        break;
                }
                context.restore();
            },
            /**
             * @param sourceEg 原始角度
             */
            transegByAction(sourceEg)
            {
                let scale = sourceEg / 90;  // 计算90度的倍数
                switch (scale)
                {
                    // 0或者-360
                    case 0:
                        return 0;
                    // -90
                    case -1:
                        return 270;
                    // -180
                    case -2:
                        return 180;
                    // -270
                    case -3:
                        return 90;
                    // 正值
                    default:
                        return sourceEg;
                }
            },
            // 打开视频
            openVideo()
            {
                this.createVideoScan(4416, 3312, currentDeviceID);
                $(".video_parent_div").css("background", "transparent");
                $("#video").css("display", "block");
                $(".aron_div_cas").css("display", "block");
                $("#screenshot_full_div").css("display", "none");
            },
            // 关闭视频
            closeVideo()
            {
                if (mediaStreamTrack == undefined)
                {
                    this.$message.error('视频未打开');
                    return false;
                }
                else
                {
                    mediaStreamTrack && mediaStreamTrack.stop();
                    mediaStreamTrack = undefined;
                }
                $(".video_parent_div").css("background", "#A0A0D2");
                $("#video").css("display", "none");
                $(".aron_div_cas").css("display", "none");
                $("#handle_select_li").css({
                    "font-weight": "normal",
                    "border": "1px solid transparent"
                });
                $(".screenshot_div").css({
                    "display": "none",
                    "width": "5px",
                    "height": "5px",
                    "top": "0px",
                    "left": "0px"
                });
                $(".video_parent_div").css({"cursor": "default"});
                $("#screenshot_full_div").css("display", "block");
                isHandleSelect = false;
            },
            // 手动框选
            handleSelect()
            {
                if (mediaStreamTrack == undefined)
                {
                    this.$message.error('视频未打开');
                    return false;
                }
                let liFontWeight = $("#handle_select_li").css("font-weight");
                if (liFontWeight == 400)
                {
                    $("#handle_select_li").css({
                        "font-weight": "bolder",
                        "border": "1px solid #0896ba"
                    });
                    $("#screenshot_full_div").css("display", "block");
                    isHandleSelect = true;
                }
                else
                {
                    $("#handle_select_li").css({
                        "font-weight": "normal",
                        "border": "1px solid transparent"
                    });
                    $(".screenshot_div,#screenshot_full_div").css({
                        "display": "none"
                    });
                    isHandleSelect = false;
                    let width = this.form.resolution.split("\*")[0];
                    let height = this.form.resolution.split("\*")[1];
                    picWidth = width;
                    picHeight = height;
                    picX = 0;
                    picY = 0;
                    $(".screenshot_div").css({
                        "width": "5px",
                        "height": "5px",
                        "top": "0px",
                        "left": "0px"
                    });
                }
                this.bindDragWindowEvent();
            },
            // 手动框选画框事件绑定
            bindDragWindowEvent()
            {
                $("#screenshot_full_div")[0].onmousedown = function (ev)
                {
                    if (!isHandleSelect)
                    {
                        return false;
                    }
                    $(".video_parent_div").css({"cursor": "crosshair"});
                    $(".screenshot_div").css({
                        "display": "block"
                    });
                    // 按下时鼠标位置
                    let clientX = ev.clientX;
                    let clientY = ev.clientY;
                    // 相对父元素的坐标位置
                    let offsetX = ev.offsetX;
                    let offsetY = ev.offsetY;
                    isDownRect = true;
                    // 移动
                    document.onmousemove = function (ev)
                    {
                        let moveCx = ev.clientX;
                        let moveCy = ev.clientY;
                        // 计算截图框大小
                        let diffX = moveCx - clientX;
                        let diffY = moveCy - clientY;
                        // 最小尺寸5个像素
                        if (!isDownRect || diffX < 5 || diffY < 5)
                        {
                            return false;
                        }
                        $(".screenshot_div,.resize-panel").css({
                            "width": diffX + "px",
                            "height": diffY + "px",
                        })
                        $(".screenshot_div").css({
                            "top": offsetY + "px",
                            "left": offsetX + "px"
                        });
                    };
                    // 弹起
                    document.onmouseup = function ()
                    {
                        isDownRect = false;
                        $(".video_parent_div").css({"cursor": "default"});
                    }
                }
            },
            /**
             * 全屏操作
             */
            fullScreen()
            {
                let ele = video;
                if (ele.requestFullscreen)
                {
                    ele.requestFullscreen();
                } else if (ele.mozRequestFullScreen)
                {
                    ele.mozRequestFullScreen();
                } else if (ele.webkitRequestFullScreen)
                {
                    ele.webkitRequestFullScreen();
                }
            },
            /**
             * 切换设备
             * @param value
             */
            changeDevice(value)
            {
                this.closeVideo();
                currentDeviceID = value;
                this.form.resolution = '1920*1080';  // 默认切为1920*1080
                this.createVideoScan(1920, 1080, value);
            },
            // 配置选择
            configSelect()
            {
                if (mediaStreamTrack == undefined)
                {
                    this.$message.error('视频未打开');
                    return false;
                }
                $(".div_handle_select").css("display", "block");
            },
            // 关闭配置选择窗体
            closeHandleConfig()
            {
                $(".div_handle_select").css("display", "none");
            },
            /**
             * 切换分辨率
             * @param value
             */
            changeResolution(value)
            {
                this.closeVideo();
                let width = value.split("\*")[0];
                let height = value.split("\*")[1];
                picWidth = width;
                picHeight = height;
                this.createVideoScan(width, height, currentDeviceID);
            },
            /**
             * 获取设备列表
             */
            getMediaDevices()
            {
                navigator.mediaDevices.enumerateDevices().then(devices =>
                {
                    let tmpArr = [];
                    devices.forEach(device =>
                    {
                        // 添加到设备列表中
                        let deviceId = device.deviceId;
                        let deviceName = device.label.split("(")[0];
                        videoMap[deviceId] = device;
                        tmpArr.push({
                            value: deviceId,
                            label: deviceName
                        });
                    })
                    this.devOptions = tmpArr;
                    let firDvId = devices.slice(0, 1)[0].deviceId;
                    this.form.deviceList = firDvId;
                    currentDeviceID = firDvId;
                });
            },
            /**
             * 连接websocket服务器
             * @param sessionId 请求sessionId
             */
            connection()
            {
                // 建立连接对象
                let socket = new SockJS(WEBSOCKET_URL);
                // 获取STOMP子协议的客户端对象
                this.stompClient = Stomp.over(socket);
                // 向服务器发起websocket连接
                this.stompClient.connect({}, (frame) =>
                    {
                        // 修改文字为【退出刮奖】
                        this.stompClient.subscribe('/topic/getResponse', response =>
                        { // 订阅服务端提供的某个topic
                            console.log(response)
                            this.solveLogMessage(response.body);
                        });
                        // //4通过stompClient.subscribe（）订阅服务器的目标是'/user/' + userId + '/msg'接收一对一的推送消息,其中userId由服务端传递过来,用于表示唯一的用户,通过此值将消息精确推送给一个用户
                        // this.stompClient.subscribe('/user/' + sessionId + '/msg', response =>
                        // {
                        //     this.solveLogMessage(response.body);
                        // });
                    },
                    (err) =>
                    {
                        // 连接发生错误时的处理函数
                        console.log('连接失败，原因：' + err)
                        // 修改文字为开始刮奖
                        this.closeVideo();
                    }
                );
            },
            /**
             * 断开连接
             */
            disconnect()
            {
                if (this.stompClient)
                {
                    this.stompClient.disconnect();
                }
            },
            /**
             * 处理推送的消息
             * @param srcMsg 原始消息，JSON字符串
             */
            solveLogMessage: function (srcMsg)
            {
                let logMsg = JSON.parse(srcMsg);
                let mid = logMsg.notifyType; // 模块ID
                let message = logMsg.notifyData; // 消息内容
                switch (mid)
                {
                    case MODEL_START_SRATCH_ID:
                        // 开始刮奖，打开摄像头
                        this.openVideo();
                        this.visible = false;
                        break;
                    case MODEL_SCRAPPER_START_ID:
                        this.settingScratchInfo(message);
                        break;
                    // 对于拍照模块，消息内容即为订单号
                    case MODEL_SCANPTHOTO_ID:
                        let orderId = message.orderId;
                        this.scanAndSave(this.form.savePath, orderId);
                        break;
                    case MODEL_EXIT_SRATCH_ID:
                        this.closeVideo();
                        break;
                }
            },
            /**
             * 设置刮奖信息
             * @param message
             */
            settingScratchInfo: function (message)
            {
                let height = message.lotteryLength; // 图片高
                let width = message.lotteryWidth; // 图片宽
                // 自动框选操作
                this.autoSelect(width, height);
            },
            /**
             * 直播回调方法
             * @param event
             */
            liveCallBack(event)
            {
                let type = event.type;
                let owner = event.src.owner;
                if (type == "error")
                {
                    $(owner).find("div[class=vcp-error-tips]").text("网络配置错误");
                }
                $("#id_live_div #back_title").remove();
            },
        },
        mounted()
        {
            // 连接websocket
            this.connection();
            deviceTimer = setInterval(this.getMediaDevices, 1000); // 定时器扫描媒体设备
            this.initVideoObj();

            // video放大缩小
            document.getElementById("video").addEventListener("mousewheel", function (ev)
            {
                // 固定滚动条
                let deltaY = ev.deltaY;
                let objectFit = $("#video").css("object-fit")
                // 通过判断deltaY是否为负数，来放大或缩小视频
                if (deltaY < 0)
                {// 小于0是放大
                    svWidth += 10;  // 每操作一次加10
                    svHeight += 10;
                    if (objectFit === 'contain')
                    {// 若当前的object-fit为contain，在放大时先改为cover，然后再放大width和height
                        $("#video").css("object-fit", "cover");
                    }
                    else
                    {
                        $("#video").css({
                            "width": svWidth + "%",
                            "height": svHeight + "%"
                        })
                    }
                }
                else
                {// 大于0是缩小
                    if (objectFit === 'cover')
                    {// 若当前的object-fit为cover，在缩小时直接减小数字，最小为100，当为100再缩小时，改为contain，然后禁止操作
                        svWidth -= 10;  // 每操作一次减10
                        svHeight -= 10;
                        $("#video").css({
                            "width": svWidth + "%",
                            "height": svHeight + "%"
                        })
                        if (svWidth == 100 || svHeight == 100)
                        {
                            $("#video").css("object-fit", "contain");
                        }
                    }
                }
                adjustVideoLocate();
            });

            // video拖动效果
            document.getElementById("video").onmousedown = function (ev)
            {
                // 获取初始鼠标位置
                let clientX = ev.clientX;
                let clientY = ev.clientY;
                // 获取video相对居左和居上尺寸
                let diffX = clientX - $("#video")[0].offsetLeft;
                let diffY = clientY - $("#video")[0].offsetTop;
                // 父级窗体宽跟高
                let pWidth = $(".video_parent_div").css("width");
                let pHeight = $(".video_parent_div").css("height");
                let pdWidth = parseFloat(pWidth.substring(0, pWidth.length - 2));
                let pdHeight = parseFloat(pHeight.substring(0, pHeight.length - 2));
                let lWidth = $("#video").css("width");
                let lHeight = $("#video").css("height");
                let ldWidth = parseFloat(lWidth.substring(0, lWidth.length - 2));
                let ldHeight = parseFloat(lHeight.substring(0, lHeight.length - 2));
                // 父级窗体减于直播窗体的值ss
                let divX = ldWidth - pdWidth;
                let divY = ldHeight - pdHeight;
                $("#video").css("cursor", "move");

                isDownPic = true;
                document.onmousemove = function (ev)
                {
                    let moveCx = ev.clientX;
                    let moveCy = ev.clientY;
                    let divCx = moveCx - diffX;
                    let divCy = moveCy - diffY;

                    if (!isDownPic)
                    {
                        return false;
                    }

                    // 左上角
                    if (divCx <= -divX && divCy <= -divY)
                    {
                        $("#video").css({
                            "top": "-" + divY + "px",
                            "left": "-" + divX + "px"
                        })
                    }
                    // 右下角
                    else if (divCx >= 0 && divCy >= 0)
                    {
                        $("#video").css({
                            "top": "0px",
                            "left": "0px"
                        })
                    }
                    // 左移
                    else if (divCx <= -divX && (divCy >= -divY && divCy <= 0))
                    {
                        $("#video").css({
                            "top": divCy + "px",
                            "left": "-" + divX + "px"
                        })
                    }
                    // 右移
                    else if (divCx >= 0 && (divCy >= -divY && divCy <= 0))
                    {
                        $("#video").css({
                            "top": divCy + "px",
                            "left": "0px"
                        })
                    }
                    // 上移
                    else if ((divCx >= -divX && divCx <= 0) && divCy <= -divY)
                    {
                        $("#video").css({
                            "top": "-" + divY + "px",
                            "left": divCx + "px"
                        })
                    }
                    // 下移
                    else if ((divCx >= -divX && divCx <= divX) && divCy >= 0)
                    {
                        $("#video").css({
                            "top": "0px",
                            "left": divCx + "px"
                        })
                    }
                    // 随机移
                    else if ((divCx >= -divX && divCx <= divX) && (divCy >= -divY && divCy <= divY))
                    {
                        $("#video").css({
                            "top": divCy + "px",
                            "left": divCx + "px"
                        })
                    }
                }
                // 释放事件
                document.onmouseup = function ()
                {
                    isDownPic = false;
                    $("#video").css("cursor", "default");
                }
            }

            // 配置窗体拖动
            document.getElementById("drag_handle_select").onmousedown = function (ev)
            {
                $("#drag_handle_select").css("cursor", "move");
                // 获取初始鼠标位置
                let clientX = ev.clientX;
                let clientY = ev.clientY;
                // 获取video相对居左和居上尺寸
                let diffX = clientX - $(".div_handle_select")[0].offsetLeft;
                let diffY = clientY - $(".div_handle_select")[0].offsetTop;

                // 父级窗体宽跟高
                let pWidth = $(".video_parent_div").css("width");
                let pHeight = $(".video_parent_div").css("height");
                let pdWidth = parseFloat(pWidth.substring(0, pWidth.length - 2));
                let pdHeight = parseFloat(pHeight.substring(0, pHeight.length - 2));
                let lWidth = $(".div_handle_select").css("width");
                let lHeight = $(".div_handle_select").css("height");
                let ldWidth = parseFloat(lWidth.substring(0, lWidth.length - 2));
                let ldHeight = parseFloat(lHeight.substring(0, lHeight.length - 2));
                // 父级窗体减于直播窗体的值
                let divX = pdWidth - ldWidth;
                let divY = pdHeight - ldHeight;
                isDownLive = true;
                document.onmousemove = function (ev)
                {
                    let moveCx = ev.clientX;
                    let moveCy = ev.clientY;
                    let divCx = moveCx - diffX;
                    let divCy = moveCy - diffY;

                    if (!isDownLive)
                    {
                        return false;
                    }
                    // 右上角
                    if (divCx >= divX && divCy < 0)
                    {
                        $(".div_handle_select").css({
                            "top": "0px",
                            "left": divX + "px"
                        })
                    }
                    else if (divCx <= 0 && divCy > divY)
                    {// 左下角
                        $(".div_handle_select").css({
                            "top": "-" + divY + "px",
                            "left": "0px"
                        })
                    }
                    else if (divCx <= 0 && (divCy >= 0 && divCy <= divY))
                    {// 左移
                        $(".div_handle_select").css({
                            "top": divCy + "px",
                            "left": "0px"
                        })
                    }
                    else if (divCx >= divX && (divCy >= 0 && divCy <= divY))
                    {// 右移
                        $(".div_handle_select").css({
                            "top": divCy + "px",
                            "left": divX + "px"
                        })
                    }
                    else if ((divCx <= divX && divCx >= 0) && divCy <= 0)
                    {// 上移
                        $(".div_handle_select").css({
                            "top": "0px",
                            "left": divCx + "px"
                        })
                    }
                    else if ((divCx <= divX && divCx >= 0) && divCy >= divY)
                    {// 下移
                        $(".div_handle_select").css({
                            "top": divY + "px",
                            "left": divCx + "px"
                        })
                    }
                    else if ((divCx <= divX && divCx >= 0) && (divCy >= 0 && divCy <= divY))
                    {// 随机移
                        $(".div_handle_select").css({
                            "top": divCy + "px",
                            "left": divCx + "px"
                        })
                    }
                }
                // 释放事件
                document.onmouseup = function ()
                {
                    isDownLive = false;
                    $("#drag_handle_select").css("cursor", "default");
                }
            }

            new ZResize({
                stage: ".video_parent_div", //舞台
                item: '#id_pic_shotscreen', //可缩放的类名
            });

            /**
             * 调整video的位置
             */
            function adjustVideoLocate()
            {
                let vpdWidth = $(".video_parent_div").css("width");
                let vpdHeight = $(".video_parent_div").css("height");
                let vWidth = $("#video").css("width");
                let vHeight = $("#video").css("height");
                let fvpdWidth = parseFloat(vpdWidth.substring(0, vpdWidth.length - 2));
                let fvpdHeight = parseFloat(vpdHeight.substring(0, vpdHeight.length - 2));
                let fvWidth = parseFloat(vWidth.substring(0, vWidth.length - 2));
                let fvHeight = parseFloat(vHeight.substring(0, vHeight.length - 2));

                // 多出来的高和宽，自动调整，保证要可视区域一直在中央
                $("#video").css({
                    "top": "-" + ((fvHeight - fvpdHeight) / 2) + "px",
                    "left": "-" + ((fvWidth - fvpdWidth) / 2) + "px"
                });
            }

            function scrollFunc(evt)
            {
                evt = evt || window.event;
                if (evt.preventDefault)
                {
                    // Firefox
                    evt.preventDefault();
                    evt.stopPropagation();
                } else
                {
                    // IE
                    evt.cancelBubble = true;
                    evt.returnValue = false;
                }
                return false;
            }

            function disabledMouseWheel(obj)
            {
                if (document.addEventListener)
                {
                    obj.addEventListener('DOMMouseScroll', scrollFunc, false);
                }//W3C
                obj.onmousewheel = scrollFunc;//IE/Opera/Chrome
            }

            //在视频元素上禁用鼠标滚动
            $('.video_parent_div').each(function ()
            {
                disabledMouseWheel(this);
            });
            // 点击效果
            $(".pop_div_cas_inner ul li").click(function ()
            {
                let index = $(this).index();
                $(".pop_div_cas_inner ul li").each(function ()
                {
                    let curIndex = $(this).index();
                    if (curIndex == index)
                    {
                        $(this).css("border", "1px solid #0896ba");
                        $(this).find("i").css("color", "#0896ba");
                    }
                    else
                    {
                        $(this).css("border", "1px solid transparent");
                        $(this).find("i").css("color", "#60626C");
                    }
                });
            });

            // 调整位置
            let elCardWidth = parseFloat($(".el-card__body").parent().css("width").replace("px", ""));
            let containerWidth = parseFloat($(".container").css("width").replace("px", ""));
            let diffWidth = (containerWidth - elCardWidth) / 2;
            let cWidth = containerWidth - diffWidth;
            $(".container").css({
                "left": diffWidth + "px",
                "width": cWidth + "px",
                "top": "20px"
            });

            // 全部替换
            String.prototype.replaceAll = function (s1, s2)
            {
                return this.replace(new RegExp(s1, "gm"), s2);
            };
        },
        beforeDestroy()
        {
            // 页面离开时断开连接
            this.disconnect();
            clearInterval(deviceTimer); // 清除定时器
            if (!mediaStreamTrack)
            {
                mediaStreamTrack && mediaStreamTrack.stop();
            }
            $(".video_parent_div").css("background", "#A0A0D2");
            $("#video").css("display", "none");
        }
    });
</script>
<style>
    body {
        margin: 0px;
        padding: 0px;
        background: #EEEEEE;
    }

    #app {
        font-family: 'Avenir', Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-align: center;
        color: #2c3e50;
    }

    .container {
        position: absolute;
        width: 80%;
    }

    .video_parent_div {
        position: relative;
        width: 100%;
        height: 100%;
        margin: 0px auto;
        background: #A0A0D2;
    }

    .pick_canvas {
        position: absolute;
        width: 100px;
        height: 100px;
        border: 2px solid #FF0000;
        margin-top: -112px;
        margin-left: 10px;
        display: none;
    }

    .pop_div_cas {
        width: 100%;
        height: 110px;
        margin: 20px auto;
        line-height: 150px;
    }

    #handle_pic_btn {
        background-color: #0896ba;
        color: #ffffff !important;
        font-size: 16px;
    }

    .pop_div_cas_inner {
        width: 100%;
        text-align: center;
    }

    .pop_div_cas_inner ul {
        list-style: none;
        padding: 0px;
        margin: 0px;
    }

    .pop_div_cas_inner ul li {
        float: left;
        width: 80px;
        height: 60px;
        cursor: pointer;
        margin-left: 65px;
        border: 1px solid transparent;
    }

    .pop_div_cas_inner span {
        display: block;
        width: 80px;
        height: 60px;
        font-size: 16px;
    }

    .pop_div_cas_inner i {
        font-size: 24px;
    }

    .aron_div_cas {
        width: 30%;
        height: 50px;
        background: #1f3240;
        opacity: 0.6;
        fill-opacity: 60;
        position: absolute;
        margin-top: 513px;
        margin-left: 282px;
        display: none;
    }

    .aron_div_cas i {
        font-size: 45px;
        color: #FFFFFF;
    }

    .aron_div_cas span {
        display: block;
        width: 80px;
        margin-left: 29px;
        cursor: pointer;
    }

    #left_aron {
        transform: rotate(-90deg);
        -ms-transform: rotate(-90deg); /* Internet Explorer */
        -moz-transform: rotate(-90deg); /* Firefox */
        -webkit-transform: rotate(-90deg); /* Safari 和 Chrome */
        -o-transform: rotate(-90deg); /* Opera */
    }

    #right_aron {
        transform: rotate(90deg);
        -ms-transform: rotate(90deg); /* Internet Explorer */
        -moz-transform: rotate(90deg); /* Firefox */
        -webkit-transform: rotate(90deg); /* Safari 和 Chrome */
        -o-transform: rotate(90deg); /* Opera */
    }

    .aron_div_cas ul {
        list-style: none;
        padding: 0;
        margin: 0;
    }

    .aron_div_cas ul li {
        float: left;
    }

    #screenshot_full_div {
        width: 100%;
        height: 100%;
        position: absolute;
        left: 0;
        top: 0;
        display: block;
    }

    .screenshot_div {
        width: 5px;
        height: 5px;
        border: 1px solid #FF0000;
        left: 0px;
        top: 0px;
        position: absolute;
        box-shadow: 0 0 0 9999em #000;
        opacity: 0.7;
        fill-opacity: 70;
        display: none;
    }

    .div_handle_select {
        width: 45%;
        height: 350px;
        border: 1px solid #CCCCCC;
        background: #FFFFFF;
        border-radius: 5px;
        z-index: 999;
        position: absolute;
        top: 145px;
        left: 432px;
        display: none;
    }

    .div_handle_select-title {
        width: 100%;
        height: 35px;
        border-bottom: 1px solid #CCCCCC;
        background: #EFEFEF;
        border-radius: 5px;
    }

    .div_handle_select-title span {
        font-size: 16px;
        line-height: 35px;
    }

    .div_handle_select-title #title_xx {
        margin-left: 60%;
        cursor: pointer;
    }

    .div_handle_select-title #title_xx:hover {
        color: #F00;
        font-weight: bolder;
    }

    .div_handle_select-content {
        width: 100%;
        height: 300px;
        margin: 10px auto;
    }
</style>
</html>